package com.example.paymentdemo.service.impl;

import com.example.paymentdemo.config.WxPayConfig;
import com.example.paymentdemo.entity.OrderInfo;
import com.example.paymentdemo.enums.OrderStatus;
import com.example.paymentdemo.enums.wxpay.WxApiType;
import com.example.paymentdemo.enums.wxpay.WxNotifyType;
import com.example.paymentdemo.service.OrderInfoService;
import com.example.paymentdemo.service.WxPayService;
import com.example.paymentdemo.util.OrderNoUtils;
import com.google.gson.Gson;
import com.wechat.pay.contrib.apache.httpclient.util.AesUtil;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author 上号
 * @Date 2022/5/17 22:15
 * @Version 1.0
 */
@Slf4j
@Service
public class WxPayServiceImpl implements WxPayService {
    @Resource
    private WxPayConfig wxPayConfig;
    @Resource
    private CloseableHttpClient wxPayClient;
    @Resource
    private OrderInfoService orderInfoService;

    /**
     * 创建订单，调用Native支付接口
     *
     * @param productId
     * @return code_url 和 订单号
     * @throws Exception
     */

    @Override
    public Map<String, Object> nativePay(Long productId) throws Exception {
        log.info("生成订单");
/*        //生成订单
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setTitle("test");
        orderInfo.setOrderNo(OrderNoUtils.getOrderNo()); //订单号
        orderInfo.setProductId(productId);
        orderInfo.setTotalFee(1); //分
        orderInfo.setOrderStatus(OrderStatus.NOTPAY.getType());*/
        // 生成订单
        OrderInfo orderInfo = orderInfoService.createOrderByProductId(productId);
        if (orderInfo != null && ! StringUtils.isEmpty(orderInfo.getCodeUrl())) {
            log.info("二维码已存在！！！！！！！");
            String codeUrl = orderInfo.getCodeUrl();
            Map<String, Object> rebody_data = new HashMap<>();
            rebody_data.put("code_url", codeUrl);
            rebody_data.put("orderNo", orderInfo.getOrderNo());
            return rebody_data;
        }
        log.info("调用统一下单API");
        //调用统一下单API   concat连接2个数组的函数
        HttpPost httpPost = new HttpPost(wxPayConfig.getDomain().concat(WxApiType.NATIVE_PAY.getType()));
        // 请求body参数
        Gson gson = new Gson();
        Map paramsMap = new HashMap();
        paramsMap.put("appid", wxPayConfig.getAppid());
        paramsMap.put("mchid", wxPayConfig.getMchId());
        paramsMap.put("description", orderInfo.getTitle());
        paramsMap.put("out_trade_no", orderInfo.getOrderNo());
        paramsMap.put("notify_url", wxPayConfig.getNotifyDomain().concat(WxNotifyType.NATIVE_NOTIFY.getType()));
        Map amountMap = new HashMap();
        amountMap.put("total", orderInfo.getTotalFee());
        amountMap.put("currency", "CNY");
        paramsMap.put("amount", amountMap);
        /*String reqdata = "{"
                + "\"time_expire\":\"2018-06-08T10:34:56+08:00\","
                + "\"amount\": {"
                + "\"total\":100,"
                + "\"currency\":\"CNY\""
                + "},"
                + "\"mchid\":\"1230000109\","
                + "\"description\":\"Image形象店-深圳腾大-QQ公仔\","
                + "\"notify_url\":\"https://www.weixin.qq.com/wxpay/pay.php\","
                + "\"out_trade_no\":\"1217752501201407033233368018\","
                + "\"goods_tag\":\"WXG\","
                + "\"appid\":\"wxd678efh567hg6787\","
                + "\"attach\":\"自定义数据说明\","
                + "\"detail\": {"
                + "\"invoice_id\":\"wx123\","
                + "\"goods_detail\": ["
                + "{"
                + "\"goods_name\":\"iPhoneX 256G\","
                + "\"wechatpay_goods_id\":\"1001\","
                + "\"quantity\":1,"
                + "\"merchant_goods_id\":\"商品编码\","
                + "\"unit_price\":828800"
                + "},"
                + "{"
                + "\"goods_name\":\"iPhoneX 256G\","
                + "\"wechatpay_goods_id\":\"1001\","
                + "\"quantity\":1,"
                + "\"merchant_goods_id\":\"商品编码\","
                + "\"unit_price\":828800"
                + "}"
                + "],"
                + "\"cost_price\":608800"
                + "},"
                + "\"scene_info\": {"
                + "\"store_info\": {"
                + "\"address\":\"广东省深圳市南山区科技中一道10000号\","
                + "\"area_code\":\"440305\","
                + "\"name\":\"腾讯大厦分店\","
                + "\"id\":\"0001\""
                + "},"
                + "\"device_id\":\"013467007045764\","
                + "\"payer_client_ip\":\"14.23.150.211\""
                + "}"
                + "}";*/
        String jsonParams = gson.toJson(paramsMap);
        log.info("请求参数" + jsonParams);
        StringEntity entity = new StringEntity(jsonParams, "utf-8");
        entity.setContentType("application/json");

        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");

        //完成签名并执行请求
        CloseableHttpResponse response = wxPayClient.execute(httpPost);

        try {
            //状态码
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) { //处理成功
                log.info("成功,return body = " + EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) {
                //处理成功，无返回Body
                log.info("成功 ，状态码" + statusCode);
            } else {
                log.info("失败,状态码 = " + statusCode + ",返回值 = " + EntityUtils.toString(response.getEntity()));
                throw new IOException("request failed");
            }
            Map<String, String> fromJson = gson.fromJson(EntityUtils.toString(response.getEntity()), HashMap.class);
            String codeUrl = fromJson.get("code_url");
            //  获取 商户订单编号
            String orderNo = orderInfo.getOrderNo();
            //保存二维码
            orderInfoService.saveCodeUrl(orderNo,codeUrl);
            // 返回二维码信息
            Map<String, Object> rebody_data = new HashMap<>();
            rebody_data.put("code_url", codeUrl);
            rebody_data.put("orderNo", orderInfo.getOrderNo());
            return rebody_data;
        } finally {
            response.close();
        }

    }

    @Override
    public void processOrder(Map<String, Object> mapBody) throws GeneralSecurityException {
        log.info("处理订单");
        // 获取解密后的 明文
        String plainText = decryptFromResource(mapBody);
    }

    /**
     * 解密
     * @param mapBody  请求体 参数 HashMap
     * @return  解密后的 明文 String
     * @throws GeneralSecurityException
     */
    private String decryptFromResource(Map<String, Object> mapBody) throws GeneralSecurityException {
        // 获取出 resource：通知数据
        Map<String, String> stringMap =(HashMap) mapBody.get("resource");
        // 数据密文
        String ciphertext = stringMap.get("ciphertext");
        log.info("数据密文==String====> {}",ciphertext);
        // 附加数据
        String associatedData = stringMap.get("associated_data");
        log.info("附加数据==String====> {}",associatedData);
        // 随机串
        String nonce = stringMap.get("nonce");
        log.info("数随机串==String====> {}",nonce);
        // 解密工具
        AesUtil aesUtil = new AesUtil((wxPayConfig.getApiV3Key().getBytes(StandardCharsets.UTF_8)));
        String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8),
                nonce.getBytes(StandardCharsets.UTF_8),
                ciphertext);
        log.info("解密后的明文String====> {}",plainText);
        return plainText;

    }
}
